热修复实现(二)

之前也分析过InstantRun的源码,前面也写了一篇热修复实现原理的文章。

But,最近遇到困难了,所在项目要做插件化,同事在开发过程中遇到了一个在5.0以下手机崩溃的问题,想着一起找找原因修复下。 但是这个bug已经折腾了我两天了,只找到原因,并没有找出任何解决方案。

深深的感觉到之前的那些都是皮毛,没有真正的去做,真正的去处理一些细节,那些都是没任何意义的。

所以这里系统学习一下,既然学习,就找一个做的最好的来学。

前面的文章也介绍了,目前存在的几个开源框架:

  • 手机淘宝基于Xposed进行了改进,产生了针对Android Dalvik虚拟机运行时的Java Method Hook技术-Dexposed。 但这个方案犹豫底层Dalvik结构过于依赖,最终无法兼容Android 5.0以后的ART虚拟机。

  • 支付宝提出了新的方案Andfix,它同样是一种底层结构替换的方案,也达到了运行时生效即时修复的效果,而且做到了Dalvik和ART全版本的兼容。然而它也 是由局限性的,且不说其底层固定结构的替换方案稳定性不好,其使用范文也存在着诸多限制,虽然可以通过代码改造来绕过限制达到同样的 修复目的,但是这种方式即不优雅也不方便。而且更大的问题是Andfix只提供了代码层面的修复,对于资源和so的修复都还未实现。

  • 其他的就是微信Tinker、饿了么的Amigo、美团的Robust,不过他们都各自有各自的局限性,或者不够稳定、或者补丁过大、或者效率低下 ,或者使用起来太繁琐,大部分技术上看起来似乎可行,但是实际体验并不好。

我们学习的就是阿里巴巴的新一代非侵入式Android热修复方案-Sophix。 它各个方面都比较优秀,使用也比较方便,唯一不支持的就是四大组件的修复。这是因为如果修复四大组件,必须在AndroidManifest里面预先插入代码组件,并且尽可能声明所有权限,这样就会给 原先的app添加很多臃肿的代码,对app运行流程的侵入性很强。

在Sophix中,唯一需要的就是初始化和请求补丁两行代码,甚至连入口Application类我们都不需要做任何修改。

这样就给了开发者最大的透明度和自由度。我们甚至重新开发了打包工具,使的补丁工具操作图形界面化,这种所见即所得的补丁生成 方式也是阿里热修复独家的,因此,Sophix的接入成本也是目前市面上所有方案里最低的。

代码修复

代码修复有两大主要方案:

  • 阿里系的底层替换方案:底层替换方案限制颇多,但是时效性最好,加载轻快,立即见效。

    底层替换方案是在已经加载了的类中直接替换掉原有的方法,是在原来类的基础上进行修改的。因而无法实现对原有类进行方法和字段的增减,因为这样将破坏原有类的结构。
    一旦补丁类中出现了方法的增加和减少,就会导致这个类以及整个dex的方法数的变化,方法数的变化伴随着方法索引的变化,这样在 访问方法时就无法正常的索引到正确的方法了。如果字段发生了增加或减少,和方法变化的情况一样,所有字段的索引都会发生变化。 而新方法中使用到这些老的示例对象时,访问新增字段就会会产生不可预期的结果。

    这是该类方案的固有限制,而底层替换方案最为人逅病的地方,在于底层替换的不稳定性。因为Hook方案,都是直接依赖修改虚拟机方法实体的具体字段。因为Art虚拟机和Dalvik虚拟机的不同,每个版本的虚拟机都要适配,而且Android系统是开源的,各个厂商都可以对代码进行改造,如果某个厂商进行了修改,那么这种通用性的替换机制就会出问题。这便是不稳定的根源。

  • 腾讯系的类加载方案:类加载方案时效性差,需要重新冷启动才能见效,但修复范围广、限制少。

类加载方案的原理是在app重新启动后让classloader去加载新的类。因为在app运行到一半的时候,所有需要发生变更的类已经被加载过了,在Android上是无法对一个类进行卸载的。如果不重启,原来的类还在虚拟机中,就无法加载新类,因此只有在下次重启的时候, 在还没走到业务逻辑之前抢先加载补丁中的新类,这样后续访问这个类的时候,就会用新类,从而达到热修复的目的。

为什么sophix更好?

既然底层替换方案和类加载方案各有优点,把他们联合起来就是最好的选择。Sophix就是同时涵盖了这两种方案,可以实现优势互补、完全兼顾的作用,可以灵活的根据实际情况自动切换。

但是Sophix有一个缺点就是,他不是开源的,而且是收费的。但是确实强大。


results matching ""

    No results matching ""